﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using LogLib;
using System.IO;
using ProcessConfig;
using ProcessConfig.ConfigType;
using ComLib.ComType;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace DetectProcessing
{
    public class DetectProcess : IDisposable
    {         
        /// <summary>
        /// 错误信息
        /// </summary>
        private string _error = "";
        public string ErrorMessage
        {
            get { return _error; }
            set { _error = value; }
        }

        /// <summary>
        /// 是否已经初始化
        /// </summary>
        private bool _bInited = false;
        public bool Inited
        {
            get { return _bInited; }
        }

        private PhotoApplyOption _applyOption = new PhotoApplyOption();

        private PixelDetectFactory PxlFactory = PixelDetectFactory.Instance;

    
        protected AssessProcess _assessor;

        protected PxlProcess _pxlProcess;

        /// <summary>
        /// 像素裁切选项组合枚举值
        /// </summary>
        protected uint _adv = 0;

        protected string _uniqueFileName;

        public bool DoQCCheck
        {
            get
            {
                return NeedQCCheck(_applyOption.ApplyType);
            }
        }

        public string UniqueFileName
        {
            get { return _uniqueFileName; }
            set { _uniqueFileName = value; }
        }

        public bool NeedQCCheck(ApplyTo app)
        {
            if (app == ApplyTo.ExitAndEntry && Configs.QC.CRJ.Enabled)
            {
                return true;
            }
            if (app == ApplyTo.PortVisa && Configs.QC.Visa.Enabled)
            {
                return true;
            }
            return false;
        }

        public DetectProcess(PhotoApplyOption option)
        {
            _applyOption = option;
            Init();
        }

        public void Init()
        {
            InitPxlPathsDic();
            _applyOption.PxlFltPath = DicPxlPaths[_applyOption.ApplyType];
            Log.WriteAsync("初始化PhotoProcess:" + _applyOption.ApplyType);
            _pxlProcess = new PxlProcess(_applyOption);
            CreatDetectHandlers();                  
            _bInited = true;
        }

        public void Dispose()
        {            
            PxlFactory.Dispose();
        }

        private Dictionary<ApplyTo, string> DicPxlPaths = new Dictionary<ApplyTo, string>();
        private void InitPxlPathsDic()
        {
            DicPxlPaths.Clear();
            DicPxlPaths.Add(ApplyTo.ExitAndEntry, "epassport_ys");
            DicPxlPaths.Add(ApplyTo.IDCard, "epassport_ys_sfz");
            DicPxlPaths.Add(ApplyTo.PortVisa, "epassport_ys_pv");
            DicPxlPaths.Add(ApplyTo.SocialSecurity, "epassport_ys_sb");
            DicPxlPaths.Add(ApplyTo.DrivingLicence, "epassport_ys_jsz");
        }

        private void CreatDetectHandlers()
        {
            try
            {
                PxlAdjustOption opt = Configs.ADOpts[_applyOption.ApplyType];
                IntPtr handle = PxlFactory[_applyOption.ApplyType];
                _assessor = new AssessProcess(handle, opt.AssessPolicies);
                PxlHandler handler = new PxlHandler(opt, _applyOption);
                _pxlProcess = new PxlProcess(handler);
                Log.WriteAsync("选择处理句柄ApplyType:" + _applyOption.ApplyType.ToString() + "," + _applyOption.PxlFltPath);
            }
            catch (Exception ex)
            {
                Log.WriteException(ex.ToString());
            }                 
        }

        private void ReleaseDetectHandlers()
        {         
            PxlFactory.Dispose();
        }

        /// <summary>
        /// 对输入图像数据进行简单的面部特征识别，不裁剪不调色不去背景不检测质量
        /// </summary>
        /// <param name="srcIn"></param>
        /// <param name="detecRes"></param>
        /// <returns></returns>
        public void HandlePrimary(RecogIn srcIn, RecogOut detecRes)
        {
            try
            {
                _pxlProcess.HandlePrimary(srcIn, detecRes);
            }
            catch (Exception ex)
            {
                _error = "正脸识别发生了异常:" + ex.Message;
                Log.WriteException(ex.ToString());
            }
        }

        /// <summary>
        /// 对捕获照片进行人脸算法识别和一所质检
        /// </summary>
        /// <param name="srcIn">输入照片</param>
        /// <param name="detecRes">输出参数集合</param>
        /// <returns></returns>
        public async Task Handle(RecogIn srcIn, RecogOut detecRes, int index = -1)
        {
            try
            {
                if (await _pxlProcess.Handle(srcIn, detecRes, index))
                {
                    if (File.Exists(detecRes.DestImagePath))
                    {
                        DoChecking(detecRes);
                    }
                    else
                    {
                        _error = "意外的错误:待检测的照片不存在:" + detecRes.DestImagePath;
                        Log.WriteAsync(_error);
                    }
                }
            }
            catch (System.Exception e)
            {
                detecRes.UnAcceptItem = UnAcceptableItem.RunningException;
                detecRes.Correction.Tips = "处理照片过程中发生了异常";
                Log.WriteException(e.ToString());
            }
        }

        public void DoChecking(RecogOut detecRes)
        {
            Log.WriteAsync("DoChecking in");
            try
            {
                _assessor.DetectAssess(detecRes);
                if (!detecRes.PassElems.PxlQcPass)
                {
                    string strLog = string.Format("图像质量检测不通过,原因:{0}", detecRes.Correction.Tips);
                    Log.WriteAsync(strLog);
                }
                else
                {
                    Log.WriteAsync("本地算法质量检测通过");
                }
                if (DoQCCheck)
                {
                    OnQCRequesting(detecRes);
                }
            }
            catch (System.Exception e)
            {
                detecRes.UnAcceptItem = UnAcceptableItem.RunningException;
                detecRes.Correction.Tips = "检测照片质量过程中发生了异常";
                Log.WriteException(e.ToString());
            }
            finally
            {
                Log.WriteAsync("DoChecking out");
            }
        }

        /// <summary>
        /// 向照片检测服务器请求处理照片，等待返回结果
        /// </summary>
        /// <returns></returns>
        private bool OnQCRequesting(RecogOut detectRes)
        {
            QCRequestArgs RequestArgs = new QCRequestArgs();
            RequestArgs.ApplyType = _applyOption.ApplyType;
            RequestArgs.Method = QCProcessMethod.QC;
            RequestArgs.CheckFileName = detectRes.DestImagePath;
            string jsonRequestString = JsonConvert.SerializeObject(RequestArgs);
            Log.WriteAsync("2发送请求:" + jsonRequestString);
            CardPhotoQCClient client = new CardPhotoQCClient("qc_pipe", ".");
            string reponseString = client.Request(jsonRequestString);
            if (string.IsNullOrEmpty(reponseString))
            {
                _error = "QCServer返回结果为空";
                detectRes.PassElems.QcDllCheck = false;
                Log.WriteAsync(_error);
                detectRes.Correction.Tips = _error;
                return false;
            }
            Log.WriteAsync("收到一所质检服务器返回信息:" + reponseString);
            QCHandleResultArgs result = JsonConvert.DeserializeObject<QCHandleResultArgs>(reponseString);
            if (!result.CallSuccess)
            {
                _error = "一所检测发生了错误:" + result.RuntimeError;
                Log.WriteAsync(_error);
                detectRes.PassElems.QcDllCheck = false;               
                detectRes.Correction.Tips = _error;
                return false;
            }
            if(result.Pass)
            {             
                detectRes.PassElems.QcDllCheck = true;
                detectRes.DestImagePath = result.DestFileName;
                _error = $"照片{result.DestFileName}一所质检合格:";
                Log.WriteAsync(_error);
            }
            else
            {
                detectRes.PassElems.QcDllCheck = false;
                detectRes.UnAcceptItem = UnAcceptableItem.QC;
                detectRes.Correction.Tips = result.UnpassReason;
                _error = $"照片{detectRes.DestImagePath}一所质检不合格:{ result.UnpassReason}";
                Log.WriteAsync(_error);
            }
            return true;
        }
    }
}
